/* -------------------------------------------------------------------------
 *
 * pgstat_archiver.c
 *	  档案统计的实现。
 *
 * 本文件包含档案统计的实现。它与pgstat.c分开，以强制统计访问/存储实现与各类型统计的细节之间的界限。
 *
 * Copyright (c) 2001-2022, PostgreSQL Global Development Group
 *
 * IDENTIFICATION
 *	  src/backend/utils/activity/pgstat_archiver.c
 * -------------------------------------------------------------------------
 */

#include "postgres.h"

#include "utils/pgstat_internal.h"
#include "utils/timestamp.h"


/*
 * 报告归档器统计信息
 */
void pgstat_report_archiver(const char *fc_xlog, bool fc_failed)
{
	PgStatShared_Archiver *fc_stats_shmem = &pgStatLocal.shmem->archiver;
	TimestampTz fc_now = GetCurrentTimestamp();

	pgstat_begin_changecount_write(&fc_stats_shmem->changecount);

	if (fc_failed)
	{
		++fc_stats_shmem->stats.failed_count;
		memcpy(&fc_stats_shmem->stats.last_failed_wal, fc_xlog,
			   sizeof(fc_stats_shmem->stats.last_failed_wal));
		fc_stats_shmem->stats.last_failed_timestamp = fc_now;
	}
	else
	{
		++fc_stats_shmem->stats.archived_count;
		memcpy(&fc_stats_shmem->stats.last_archived_wal, fc_xlog,
			   sizeof(fc_stats_shmem->stats.last_archived_wal));
		fc_stats_shmem->stats.last_archived_timestamp = fc_now;
	}

	pgstat_end_changecount_write(&fc_stats_shmem->changecount);
}

/*
 * 用于 SQL 可调用的 pgstat* 函数的支持函数。返回
 * 指向归档器统计结构的指针。
 */
PgStat_ArchiverStats *
pgstat_fetch_stat_archiver(void)
{
	pgstat_snapshot_fixed(PGSTAT_KIND_ARCHIVER);

	return &pgStatLocal.snapshot.archiver;
}

void pgstat_archiver_reset_all_cb(TimestampTz fc_ts)
{
	PgStatShared_Archiver *fc_stats_shmem = &pgStatLocal.shmem->archiver;

	/* 请参见 PgStatShared_Archiver 以上的说明以了解重置协议 */
	LWLockAcquire(&fc_stats_shmem->lock, LW_EXCLUSIVE);
	pgstat_copy_changecounted_stats(&fc_stats_shmem->reset_offset,
									&fc_stats_shmem->stats,
									sizeof(fc_stats_shmem->stats),
									&fc_stats_shmem->changecount);
	fc_stats_shmem->stats.stat_reset_timestamp = fc_ts;
	LWLockRelease(&fc_stats_shmem->lock);
}

void pgstat_archiver_snapshot_cb(void)
{
	PgStatShared_Archiver *fc_stats_shmem = &pgStatLocal.shmem->archiver;
	PgStat_ArchiverStats *fc_stat_snap = &pgStatLocal.snapshot.archiver;
	PgStat_ArchiverStats *fc_reset_offset = &fc_stats_shmem->reset_offset;
	PgStat_ArchiverStats fc_reset;

	pgstat_copy_changecounted_stats(fc_stat_snap,
									&fc_stats_shmem->stats,
									sizeof(fc_stats_shmem->stats),
									&fc_stats_shmem->changecount);

	LWLockAcquire(&fc_stats_shmem->lock, LW_SHARED);
	memcpy(&fc_reset, fc_reset_offset, sizeof(fc_stats_shmem->stats));
	LWLockRelease(&fc_stats_shmem->lock);

	/* 通过重置偏移量进行补偿 */
	if (fc_stat_snap->archived_count == fc_reset.archived_count)
	{
		fc_stat_snap->last_archived_wal[0] = 0;
		fc_stat_snap->last_archived_timestamp = 0;
	}
	fc_stat_snap->archived_count -= fc_reset.archived_count;

	if (fc_stat_snap->failed_count == fc_reset.failed_count)
	{
		fc_stat_snap->last_failed_wal[0] = 0;
		fc_stat_snap->last_failed_timestamp = 0;
	}
	fc_stat_snap->failed_count -= fc_reset.failed_count;
}
